import { memo, useRef } from 'react'
import { useDrag, useDrop } from 'react-dnd'
import type { CSSProperties, FC } from 'react'
import { ItemTypes } from '../CommandList/ItemTypes'
import { CheckOutlined, ClockCircleOutlined, WarningOutlined, CloseOutlined } from '@ant-design/icons';
import classNames from 'classnames';
import { COMMANDS } from '@repo/executor/src/playback_tree/constants';

const style: CSSProperties = {
  border: '1px dashed gray',
  padding: '0.5rem 1rem',
  marginBottom: '.5rem',
  backgroundColor: 'white',
  cursor: 'move',
}

export interface CommandProps {
  index: number;
  moveCommand: (index: number, to: number, commandData: any) => void;
  commandData: any;
  level: number;
  taskExecutionResult?: {
    dones: Set<number>, // 成功的
    errors: Set<number>, // 失败的
    warnings: Set<number> // 报警的
  };// 执行结果
}

interface Item {
  type: string;
  cmd: string;
  description: string;
  index: number;
  dragIndex: number;
}

export const Command: FC<CommandProps> = memo(function Card({
  index,
  moveCommand,
  commandData,
  level,
  taskExecutionResult
}) {
  const ref = useRef<HTMLSpanElement | null>(null);
  const [{ isDragging }, drag] = useDrag(
    () => ({
      type: ItemTypes.CARD,
      item: { ...commandData, type: ItemTypes.CARD, dragIndex: index },
      collect: (monitor) => ({
        isDragging: monitor.isDragging(),
      }),
      end: (item, monitor) => {
        const { dragIndex } = item
        const didDrop = monitor.didDrop()
        if (!didDrop) {
          // 区域外取消
          moveCommand(index, dragIndex, {
            cmd: item.cmd,
            description: item.description
          })
        }
      },
      isDragging: (monitor) => {
        return monitor.getItem()?.dragIndex === index || monitor.getItem()?.dragIndex === -1
      }
    }),
    [index, moveCommand, commandData],
  )

  const [, drop] = useDrop(
    () => ({
      accept: [ItemTypes.CARD, ItemTypes.CMD],
      hover(item: Item, monitor) {
        const isOver = monitor.isOver({ shallow: true })
        console.log('item isOver', isOver)
        const dragIndex = item.dragIndex;
        const hoverIndex = index;

        if (dragIndex === hoverIndex) {
          return
        }
        const clientOffset = monitor.getClientOffset();
        const el: any = ref.current;
        if (!el || !clientOffset) return;

        const hoverBoundingRect = el.getBoundingClientRect();
        const halfHeight = hoverBoundingRect.height / 2
        const yInElement = clientOffset.y - hoverBoundingRect.top

        if (dragIndex < hoverIndex && yInElement < halfHeight) {
          return
        }

        // Dragging upwards
        if (dragIndex > hoverIndex && yInElement > halfHeight) {
          return
        }

        moveCommand(dragIndex, hoverIndex, {
          cmd: item.cmd,
          description: item.description
        })
        item.dragIndex = hoverIndex;
      },
    }),
    [moveCommand, index],
  )

  const opacity = isDragging ? 0 : 1;

  return (
    <div ref={(node) => {
      ref.current = node;
      drag(drop(node))
    }}
      className={classNames('flex gap-4 px-4 overflow-hidden rounded', {
        'command-pending': !taskExecutionResult?.dones.has(index) &&
          !taskExecutionResult?.warnings.has(index) &&
          !taskExecutionResult?.errors.has(index),
        'command-done': taskExecutionResult?.dones.has(index),
        'command-warning': taskExecutionResult?.warnings.has(index),
        'command-error': taskExecutionResult?.errors.has(index),
      })}
      style={{ ...style, opacity, marginLeft: level * 24 }}
    >
      <div className='flex-none flex gap-2' title={COMMANDS.get(commandData.cmd)?.description}>
        {
          taskExecutionResult?.dones.has(index) &&
          <CheckOutlined className="text-green-400" />
        }
        {
          taskExecutionResult?.warnings.has(index) &&
          <WarningOutlined className="text-yellow-400" />
        }
        {
          taskExecutionResult?.errors.has(index) &&
          <CloseOutlined className="text-red-400" />
        }
        {
          !taskExecutionResult?.dones.has(index) &&
          !taskExecutionResult?.warnings.has(index) &&
          !taskExecutionResult?.errors.has(index) &&
          <ClockCircleOutlined />
        }
        <span>
          {COMMANDS.get(commandData.cmd)?.name || commandData.cmd}
        </span>
      </div>
      {
        commandData.target && <div className='flex overflow-hidden gap-2'>
          <span className='flex-none' title={COMMANDS.get(commandData.cmd)?.target.description}>{COMMANDS.get(commandData.cmd)?.target.name || 'target'}:</span>
          <span className='flex-1 text-blue-600 overflow-hidden text-ellipsis whitespace-nowrap' title={commandData.target}>{commandData.target}</span>
        </div>
      }
      {
        commandData.value && <div className='flex flex-none overflow-hidden gap-2'>
          <span className='flex-none' title={COMMANDS.get(commandData.cmd)?.value.description}>{COMMANDS.get(commandData.cmd)?.value.name || 'value'}:</span>
          <span className='flex-1 text-blue-600 overflow-hidden text-ellipsis whitespace-nowrap' title={commandData.value}>{commandData.value}</span>
        </div>
      }
    </div>
  )
})
